package com.liholin.springboot.sample.service.impl;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheUpdate;
import com.alicp.jetcache.anno.Cached;
import com.alicp.jetcache.anno.CreateCache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.liholin.springboot.sample.annotation.DataIsolate;
import com.liholin.springboot.sample.bean.LoginBean;
import com.liholin.springboot.sample.bean.LoginResponse;
import com.liholin.springboot.sample.bean.Member;
import com.liholin.springboot.sample.bean.SortMemberBean;
import com.liholin.springboot.sample.configdata.ResponseData;
import com.liholin.springboot.sample.exception.ErrorStatus;
import com.liholin.springboot.sample.mapper.MemberMapper;
import com.liholin.springboot.sample.service.MemberService;
import com.liholin.springboot.sample.service.RedisService;
import com.liholin.springboot.sample.utils.AssignmentUtils;
import com.liholin.springboot.sample.utils.JWTUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static java.lang.invoke.LambdaMetafactory.FLAG_SERIALIZABLE;

@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {

    @Value("${newshop.constSalt}")
    private String constSalt;

    @Autowired
    private RedisService redisService;


    @CreateCache(name = "jetCache::", expire = 3600, timeUnit = TimeUnit.SECONDS/*,cacheType = CacheType.REMOTE 远程缓存 默认的  both 本地远程都用 local 本地缓存*/)
    // 3600s 过期时间
    private Cache<String, String> jetCache;

    @Override
    public IPage<Member> getSortMember(int page, int pageSize, int desc, String sort, String query) {
        IPage<Member> memberPage = new Page<>(page, pageSize);
//        QueryWrapper query = new QueryWrapper();
//        query.orderByAsc(sort);
//        LambdaQueryWrapper<Member> queryWrapper = query.lambda();
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        try {
            Class<? extends Member> aClass = Member.class;
            Field field = aClass.getDeclaredField(sort);
            if (desc == 1) {
                queryWrapper.orderByDesc(getFunctionField(aClass, field));
            } else {
                queryWrapper.orderByAsc(getFunctionField(aClass, field));
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        SortMemberBean sortMemberBean = new Gson().fromJson(query, SortMemberBean.class);
        if (sortMemberBean != null) {
            queryWrapper.eq(sortMemberBean.getMemberId() != 0, Member::getMemberId, sortMemberBean.getMemberId())
                    .like(StringUtils.isNotBlank(sortMemberBean.getName()), Member::getName, sortMemberBean.getName())
                    .like(StringUtils.isNotBlank(sortMemberBean.getEmail()), Member::getEmail, sortMemberBean.getEmail())
                    .eq(sortMemberBean.getAge() != 0, Member::getAge, sortMemberBean.getAge());
        }
        jetCache.put("tele", "jetCache");
        return getBaseMapper().selectPage(memberPage, queryWrapper);
    }

    @Override
    @Cached(name = "member::", key = "#id")
    public Member getMemberListJetCache(int id) {
        return getBaseMapper().getMemberListJetCache(id);
    }

    @Override
    @CacheUpdate(name = "member::", key = "#member.memberId", value = "#member")
    public ResponseData updateMemberListJetCache(Member member) {
        LambdaUpdateWrapper<Member> updateWrapper = new LambdaUpdateWrapper<>();
        LambdaUpdateWrapper<Member> wrapper = updateWrapper.eq(Member::getMemberId, member.getMemberId()).last("limit 1");
        Member member1 = getOne(wrapper);
        if (member1 == null) {
            return ResponseData.Companion.error("查无此人,修改失败", ErrorStatus.ERROR_400011);
        }
        // 如果member中某个字段为null 将 member1的该字段赋值给 member
        AssignmentUtils.entityClassAssignment(member1, member);

        wrapper.set(Member::getAge, member.getAge())
                .set(StringUtils.isNotBlank(member.getName()), Member::getName, member.getName())
                .set(StringUtils.isNotBlank(member.getEmail()), Member::getEmail, member.getEmail());
        return getBaseMapper().update(null, updateWrapper) == 1 ? ResponseData.Companion.ok("修改成功") :
                ResponseData.Companion.error("修改失败", ErrorStatus.ERROR_400011);
    }

    @Override
    @CacheInvalidate(name = "member::", key = "#id")
    public int deleteMemberListJetCache(int id) {
//        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Member::getMemberId, id);
        return 1;
    }

    @DataIsolate
    @Override
    public String sqlMontage() {
        return "";
    }

    @Override
    public IPage<Member> getSortMemberList(int pageNumber, int pageSize, int desc, String sort, String query) {
        Page<Member> page = new Page<>(pageNumber, pageSize);
        SortMemberBean sortMemberBean = new Gson().fromJson(query, SortMemberBean.class);
        System.out.println("jetCache====" + jetCache.get("tele"));
        return getBaseMapper().getSortMember(page, desc, sort, sortMemberBean);
    }

    @Override
    public List<Member> selectServicePage(int pageNumber, int pageSize, int desc, String sort, String query) {
        SortMemberBean sortMemberBean = new Gson().fromJson(query, SortMemberBean.class);
        return getBaseMapper().selectServicePage(desc, sort, sortMemberBean);
    }

    @Override
    public ResponseData saveMember(Member member) {
        LambdaQueryWrapper<Member> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //getOne 如果有多条会抛异常 利用 wrapper.last("limit 1") 随机取一条就不会报错了
        lambdaQueryWrapper.eq(Member::getEmail, member.getEmail()).last("limit 1");
        Member one = getOne(lambdaQueryWrapper);
        if (one != null) {
            return ResponseData.Companion.error(ErrorStatus.EXIST_RECORD_ERROR);
        }
        System.out.println("============" + redisService.get("loginToken"));
        return save(member) ? ResponseData.Companion.ok("添加成功", null) : ResponseData.Companion.error();
    }

    @Override
    public ResponseData login(LoginBean loginBean, String app) {
//        Useraccount useraccount = new Useraccount();
//        LocalDateTime localDateTime = LocalDateTime.now();
//        useraccount.setMobile(loginBean.getUserName());
//        UUID uuid = UUID.randomUUID();
//        String un = uuid.toString().replace("-", "");
//        useraccount.setHguid(un);
//        String password = null;
//        try {
//            password = EncryptionUtil.Encode(constSalt, loginBean.getPassWord());
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//        useraccount.setPassword(password);
//        String invitationCode = "";
//        int lastUserId = useraccountService.getLastUserId();
//        invitationCode = InvitationCodeUtil.toSerialCode(lastUserId);
//        useraccount.setInvitationcode(invitationCode);

//        useraccount.setUnixts(DateUtil.getDateTs());
//        useraccount.setIsactive(true);
//        useraccount.setUserstatus(1);
//        useraccount.setIsonline(true);
//        useraccount.setTs(localDateTime);
//        useraccount.setCreatetime(localDateTime);
//        useraccount.setLevel(1);
//        useraccount.setHeadphoto("http://xinlingshouoss.lianwukeji.com/headPhoto.png");

        HashMap<String, String> map = new HashMap<>();

        map.put("un", "dkjfek");
        map.put("userId", "1");
        map.put("app", app);
        //生成token
        String token = JWTUtil.generateToken(map);
        Map<String,Object> userInfoMap = null;
        userInfoMap = redisService.HGetByKey(map.get("un"));
        if (userInfoMap == null || userInfoMap.size() == 0){
            userInfoMap = new HashMap<>();
        }
        userInfoMap.put(app,token);
        redisService.HPutMap(map.get("un"),userInfoMap);
        return ResponseData.Companion.ok("登录成功", new LoginResponse(token));
    }


    /**
     * 如果需要根据传入的名字进行排序 用到反射
     * xxx
     *
     * @param entityClass 实体类
     * @param field       属性名
     * @return SFunction
     */
    private SFunction getFunctionField(Class<?> entityClass, Field field) {
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodType methodType = MethodType.methodType(field.getType(), entityClass);
        final CallSite site;
        String filedName = field.getName();
        String getFunName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
        try {
            site = LambdaMetafactory.altMetafactory(lookup,
                    "invoke",
                    MethodType.methodType(SFunction.class),
                    methodType,
                    lookup.findVirtual(entityClass, getFunName, MethodType.methodType(field.getType())),
                    methodType, FLAG_SERIALIZABLE);
            return (SFunction) site.getTarget().invokeExact();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }
}
